#pragma once

#include "common.h"
#include "yyjson.h"
#include <format>
#include <iostream>
#include <map>
#include <set>
#include <vector>

#define YYJSON_CREATE_AND_MANAGE(doc, root, obj) \
    yyjson_mut_doc* doc  = nullptr;              \
    yyjson_mut_val* root = nullptr;              \
    yyjson::create(&doc, &root, obj);            \
    on_scope_exit(                               \
        [&doc]()                                 \
        {                                        \
            if (doc) yyjson_mut_doc_free(doc);   \
        });

#define YYJSON_CREATE_AND_MANAGE_OBJ(doc, root) YYJSON_CREATE_AND_MANAGE(doc, root, true)
#define YYJSON_CREATE_AND_MANAGE_ARR(doc, root) YYJSON_CREATE_AND_MANAGE(doc, root, false)

namespace yyjson
{
inline yyjson_doc* load_file(const char* path, yyjson_read_flag flg = 0, const yyjson_alc* alc = nullptr, yyjson_read_err* err = nullptr)
{
    yyjson_doc* doc = yyjson_read_file(path, flg, alc, err);
    if (doc == nullptr) throw std::underflow_error(std::format("failed to load {}", path).c_str());
    return doc;
}

/**
 * @brief 加载内存中的josn，失败抛异常
 */
inline yyjson_doc* load(const char* json, size_t len, yyjson_read_flag flg = 0)
{
    yyjson_doc* doc = yyjson_read(json, len, flg);
    if (doc == nullptr) throw std::underflow_error("failed to parse JSON.");
    return doc;
}

/**
 * @brief 获取root节点，失败抛异常
 */
inline yyjson_val* get_root_obj(yyjson_doc* doc)
{
    yyjson_val* root = yyjson_doc_get_root(doc);
    if (!yyjson_is_obj(root)) throw std::underflow_error("root is not an object.");
    return root;
}

/**
 * @brief 获取obj节点，失败抛异常
 */
inline yyjson_val* get_obj(yyjson_val* val, const char* key)
{
    yyjson_val* obj = yyjson_obj_get(val, key);
    if (obj == nullptr) throw std::underflow_error(std::string("have not an object for key:").append(key).c_str());
    return obj;
}

/**
 * @brief 获取root节点，失败抛异常
 */
inline yyjson_val* get_root_array(yyjson_doc* doc)
{
    yyjson_val* root = yyjson_doc_get_root(doc);
    if (!yyjson_is_arr(root)) throw std::underflow_error("root is not an array.");
    return root;
}

/**
 * @brief 获取json字段数据
 */
template <class T>
inline bool get_value(yyjson_val* obj, const char* key, T& result)
{
    yyjson_val* element = yyjson_obj_get(obj, key);
    if (!element)
    {
        // std::cerr << "Failed to get integer for key: " << key << std::endl;
        return false;
    }

    if constexpr (std::is_same_v<T, std::string>)
    {
        if (yyjson_is_str(element))
        {
            result = yyjson_get_str(element);
        }
    }
    else if constexpr (std::is_same_v<T, int>)
    {
        if (yyjson_is_int(element))
        {
            result = yyjson_get_int(element);
        }
    }
    else if constexpr (std::is_same_v<T, bool>)
    {
        if (yyjson_is_bool(element))
        {
            result = yyjson_get_bool(element);
        }
    }
    else if constexpr (std::is_same_v<T, uint64_t>)
    {
        if (yyjson_is_uint(element))
        {
            result = yyjson_get_uint(element);
        }
    }
    else if constexpr (std::is_same_v<T, int64_t>)
    {
        // if (yyjson_is_sint(element))
        {
            result = yyjson_get_sint(element);
        }
    }
    else if constexpr (std::is_same_v<T, double>)
    {
        if (yyjson_is_real(element))
        {
            result = yyjson_get_real(element);
        }
    }
    else
    {
        return false;
    }

    return true;
}

/**
 * @brief 获取json object里的字段数据，并存入k/v，不对obj/arr获取
 */
inline void get_value(yyjson_val* obj, std::map<std::string, std::string>& outValue)
{
    if (!obj || !yyjson_is_obj(obj))
        return;

    size_t      idx, max;
    yyjson_val *key, *val;
    yyjson_obj_foreach(obj, idx, max, key, val)
    {
        const char* k = yyjson_get_str(key);
        switch (yyjson_get_type(val))
        {
            case YYJSON_TYPE_STR:
                outValue[k] = yyjson_get_str(val);
                break;
            case YYJSON_TYPE_NUM:
            {
                double num  = yyjson_get_real(val);
                outValue[k] = std::to_string(num);
                break;
            }
            case YYJSON_TYPE_BOOL:
                outValue[k] = yyjson_get_bool(val) ? "true" : "false";
                break;
            case YYJSON_TYPE_NULL:
                outValue[k] = "null";
                break;
            default:
                break;
        }
    }
}

// 浅拷贝，value生命周期需要大于等于doc
inline void add_array(yyjson_mut_doc* doc, yyjson_mut_val* val_obj, const char* field, const std::set<std::string>& values, bool must_exists = false)
{
    // 为空，且字段没有一定要存在，返回
    if (values.empty() && !must_exists) return;
    if (!val_obj || !yyjson_mut_is_obj(val_obj)) return;

    yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, val_obj, field);
    if (arr)
    {
        for (const auto& str : values)
        {
            yyjson_mut_arr_add_str(doc, arr, str.c_str());
        }
    }
}

// 深拷贝，value生命周期随意
inline void add_array_deep_copy(yyjson_mut_doc* doc, yyjson_mut_val* val_obj, const char* field, const std::set<std::string>& values,
                                bool must_exists = false)
{
    // 为空，且字段没有一定要存在，返回
    if (!values.empty() && !must_exists) return;
    if (!val_obj || !yyjson_mut_is_obj(val_obj)) return;

    yyjson_mut_val* key = yyjson_mut_strcpy(doc, field);
    yyjson_mut_val* val = yyjson_mut_arr(doc);
    if (!yyjson_mut_obj_add(val_obj, key, val))
    {
        return;
    }

    for (const auto& str : values)
    {
        yyjson_mut_arr_add_strcpy(doc, val, str.c_str());
    }
}

template <class T>
inline bool get_array(yyjson_val* obj, const char* key, std::vector<T>& result)
{
    result.clear();
    yyjson_val* arr = yyjson_obj_get(obj, key);
    if (!arr || !yyjson_is_arr(arr))
    {
        // std::cerr << "Failed to get array for key: " << key << std::endl;
        return false;
    }

    size_t size = yyjson_arr_size(arr);
    result.reserve(size);

    for (size_t i = 0; i < size; ++i)
    {
        yyjson_val* element = yyjson_arr_get(arr, i);
        if constexpr (std::is_same_v<T, std::string>)
        {
            if (yyjson_is_str(element))
            {
                const char* str = yyjson_get_str(element);
                result.emplace_back(str);
            }
        }
        else if constexpr (std::is_same_v<T, int>)
        {
            if (yyjson_is_int(element))
            {
                int value = yyjson_get_int(element);
                result.push_back(value);
            }
        }
        else
        {
            return false;
        }
        // else/// 其他感觉不太实际，先实现这两个
        //{
        //	if (yyjson_is_raw(element))
        //	{
        //		const char* raw = yyjson_get_raw(element);
        //		result.push_back(raw);
        //	}
        // }
    }

    return true;
}

template <class T>
inline bool get_array(yyjson_val* obj, const char* key, std::set<T>& result)
{
    result.clear();
    yyjson_val* arr = yyjson_obj_get(obj, key);
    if (!arr || !yyjson_is_arr(arr))
    {
        return false;
    }

    size_t size = yyjson_arr_size(arr);

    for (size_t i = 0; i < size; ++i)
    {
        yyjson_val* element = yyjson_arr_get(arr, i);
        if constexpr (std::is_same_v<T, std::string>)
        {
            if (yyjson_is_str(element))
            {
                const char* str = yyjson_get_str(element);
                result.insert(str);
            }
        }
        else if constexpr (std::is_same_v<T, int>)
        {
            if (yyjson_is_int(element))
            {
                int value = yyjson_get_int(element);
                result.insert(value);
            }
        }
        else
        {
            return false;
        }
    }

    return true;
}

inline bool for_earch(yyjson_val* obj, std::map<std::string, std::string>& out)
{
    out.clear();

    yyjson_val*     key;
    yyjson_val*     value;
    yyjson_obj_iter iter;

    yyjson_obj_iter_init(obj, &iter);
    while ((key = yyjson_obj_iter_next(&iter)))
    {
        const char* key_str = yyjson_get_str(key);
        value               = yyjson_obj_iter_get_val(key);

        if (yyjson_get_type(value) == YYJSON_TYPE_STR)
        {
            out[key_str] = yyjson_get_str(value);
        }
        else if (yyjson_get_type(value) == YYJSON_TYPE_NUM)
        {
            out[key_str] = std::to_string(yyjson_get_num(value));
        }
        else if (yyjson_get_type(value) == YYJSON_TYPE_BOOL)
        {
            out[key_str] = yyjson_get_bool(value) ? "true" : "false";
        }
        else
        {
            continue;
        }
    }

    return !out.empty();
}

//----------------------------------------------------
inline bool deep_copy_num(yyjson_val* src_val, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_val, const char* field)
{
    if (!field) return false;
    yyjson_mut_val* new_num = NULL;
    if (yyjson_is_real(src_val))
    {
        new_num = yyjson_mut_real(dst_doc, yyjson_get_real(src_val));
    }
    else if (yyjson_is_sint(src_val))
    {
        new_num = yyjson_mut_sint(dst_doc, yyjson_get_sint(src_val));
    }
    else if (yyjson_is_uint(src_val))
    {
        new_num = yyjson_mut_uint(dst_doc, yyjson_get_uint(src_val));
    }
    else /*if (yyjson_is_int(src_val))*/
    {
        new_num = yyjson_mut_int(dst_doc, yyjson_get_int(src_val));
    }

    if (!new_num) return false;

    yyjson_mut_val* key = yyjson_mut_strcpy(dst_doc, field);
    if (!key) return false;

    yyjson_mut_obj_add(dst_val, key, new_num);

    return true;
}

inline bool deep_copy_str(yyjson_val* src_val, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_val, const char* field)
{
    if (!field) return false;
    const char* str = yyjson_get_str(src_val);

    yyjson_mut_val* new_str = yyjson_mut_strcpy(dst_doc, str);
    if (!new_str) return false;

    yyjson_mut_val* key = yyjson_mut_strcpy(dst_doc, field);
    if (!key) return false;

    yyjson_mut_obj_add(dst_val, key, new_str);

    return true;
}

inline bool deep_copy_bool(yyjson_val* src_val, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_val, const char* field)
{
    if (!field) return false;
    bool            value    = yyjson_get_bool(src_val);
    yyjson_mut_val* new_bool = yyjson_mut_bool(dst_doc, value);
    if (!new_bool) return false;

    yyjson_mut_val* key = yyjson_mut_strcpy(dst_doc, field);
    if (!key) return false;

    yyjson_mut_obj_add(dst_val, key, new_bool);

    return true;
}

inline bool deep_copy_null(yyjson_val* src_val, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_val, const char* field)
{
    if (!field) return false;
    yyjson_mut_val* new_null = yyjson_mut_null(dst_doc);
    if (!new_null) return false;

    yyjson_mut_val* key = yyjson_mut_strcpy(dst_doc, field);
    if (!key) return false;

    yyjson_mut_obj_add(dst_val, key, new_null);

    return true;
}
inline bool deep_copy_arr(yyjson_val* src_arr, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_arr);
inline bool deep_copy_obj(yyjson_val* src_obj, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_obj)
{
    size_t      idx, max;
    yyjson_val *key, *val;
    yyjson_obj_foreach(src_obj, idx, max, key, val)
    {
        const char*     key_str = yyjson_get_str(key);
        yyjson_mut_val* new_key = yyjson_mut_strcpy(dst_doc, key_str);
        if (!new_key) return false;

        yyjson_mut_val* new_val = nullptr;
        switch (yyjson_get_type(val))
        {
            case YYJSON_TYPE_NULL:
                if (!deep_copy_null(val, dst_doc, dst_obj, key_str)) return false;
                break;
            case YYJSON_TYPE_BOOL:
                if (!deep_copy_bool(val, dst_doc, dst_obj, key_str)) return false;
                break;
            case YYJSON_TYPE_NUM:
                if (!deep_copy_num(val, dst_doc, dst_obj, key_str)) return false;
                break;
            case YYJSON_TYPE_STR:
                if (!deep_copy_str(val, dst_doc, dst_obj, key_str)) return false;
                break;
            case YYJSON_TYPE_ARR:
            {
                new_val = yyjson_mut_arr(dst_doc);
                if (!new_val || !deep_copy_arr(val, dst_doc, new_val)) return false;
                yyjson_mut_obj_add(dst_obj, new_key, new_val);
                break;
            }
            case YYJSON_TYPE_OBJ:
            {
                new_val = yyjson_mut_obj(dst_doc);
                if (!new_val || !deep_copy_obj(val, dst_doc, new_val)) return false;
                yyjson_mut_obj_add(dst_obj, new_key, new_val);
                break;
            }
            default:
                return false;
        }
    }

    return true;
}

inline bool deep_copy_arr(yyjson_val* src_arr, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_arr)
{
    size_t      idx, max;
    yyjson_val* val;
    yyjson_arr_foreach(src_arr, idx, max, val)
    {
        yyjson_mut_val* new_val = nullptr;
        switch (yyjson_get_type(val))
        {
            case YYJSON_TYPE_NULL:
                new_val = yyjson_mut_null(dst_doc);
                break;
            case YYJSON_TYPE_BOOL:
                new_val = yyjson_mut_bool(dst_doc, yyjson_get_bool(val));
                break;
            case YYJSON_TYPE_NUM:
                if (yyjson_is_real(val))
                {
                    new_val = yyjson_mut_real(dst_doc, yyjson_get_real(val));
                }
                else if (yyjson_is_sint(val))
                {
                    new_val = yyjson_mut_sint(dst_doc, yyjson_get_sint(val));
                }
                else if (yyjson_is_uint(val))
                {
                    new_val = yyjson_mut_uint(dst_doc, yyjson_get_uint(val));
                }
                else /*if (yyjson_is_int(value)) */
                {
                    new_val = yyjson_mut_int(dst_doc, yyjson_get_int(val));
                }
                break;
            case YYJSON_TYPE_STR:
                new_val = yyjson_mut_strcpy(dst_doc, yyjson_get_str(val));
                break;
            case YYJSON_TYPE_ARR:
            {
                new_val = yyjson_mut_arr(dst_doc);
                if (!new_val || !deep_copy_arr(val, dst_doc, new_val)) return false;
                break;
            }
            case YYJSON_TYPE_OBJ:
            {
                new_val = yyjson_mut_obj(dst_doc);
                if (!new_val || !deep_copy_obj(val, dst_doc, new_val)) return false;
                break;
            }
            default:
                return false;
        }
        if (new_val)
        {
            bool ret = yyjson_mut_arr_add_val(dst_arr, new_val);
        }
    }

    return true;
}

/**
 * @brief 深拷贝yyjson_val到yyjson_mut_val
 * @param src_val只读yyjson val，待拷贝源数据
 * @param dst_doc可写yyjson mut doc
 * @param dst_val可写，需要传入obj或arr，单纯值拷贝就使用其他接口即可
 * @return 成功/失败
 */
inline bool deep_copy(yyjson_val* src_val, yyjson_mut_doc* dst_doc, yyjson_mut_val* dst_val, const char* field = nullptr)
{
    switch (yyjson_get_type(src_val))
    {
        case YYJSON_TYPE_OBJ:
        {
            if (field != nullptr)
            {
                yyjson_mut_val* tmp = yyjson_mut_obj_add_obj(dst_doc, dst_val, field);
                return deep_copy_obj(src_val, dst_doc, tmp);
            }
            else
            {
                return deep_copy_obj(src_val, dst_doc, dst_val);
            }
        }
        case YYJSON_TYPE_ARR:
        {
            if (yyjson_mut_is_arr(dst_val))
            {  // 外部已经创建好arr
                return deep_copy_arr(src_val, dst_doc, dst_val);
            }
            else if (field)
            {  // 外部传入的是obj
                yyjson_mut_val* tmp = yyjson_mut_obj_add_arr(dst_doc, dst_val, field);
                return deep_copy_arr(src_val, dst_doc, tmp);
            }
        }
        case YYJSON_TYPE_NUM:
            return deep_copy_num(src_val, dst_doc, dst_val, field);
        case YYJSON_TYPE_BOOL:
            return deep_copy_bool(src_val, dst_doc, dst_val, field);
        case YYJSON_TYPE_STR:
            return deep_copy_str(src_val, dst_doc, dst_val, field);
        case YYJSON_TYPE_NULL:
            return deep_copy_null(src_val, dst_doc, dst_val, field);
        default:
            break;
    }
    return false;
}

//----------------------------------------------------
inline yyjson_val* for_earch_obj(yyjson_val* obj, const std::vector<std::string>& node_list, const int cur_depth = 0);
inline yyjson_val* for_earch_arr(yyjson_val* arr, const std::vector<std::string>& node_list, const int cur_depth = 0);

inline yyjson_val* for_earch_arr(yyjson_val* arr, const std::vector<std::string>& node_list, const int cur_depth)
{
    if (node_list.size() <= cur_depth)
    {
        return nullptr;
    }

    size_t      idx, max;
    yyjson_val *val, *ret = nullptr;
    yyjson_arr_foreach(arr, idx, max, val)
    {
        switch (yyjson_get_type(val))
        {
            case YYJSON_TYPE_ARR:
            {
                ret = for_earch_arr(val, node_list, cur_depth);
            }
            case YYJSON_TYPE_OBJ:
            {
                ret = for_earch_obj(val, node_list, cur_depth + 1);
            }
            default:
                break;
        }

        if (ret) return ret;
    }

    return nullptr;
}

inline yyjson_val* for_earch_obj(yyjson_val* obj, const std::vector<std::string>& node_list, const int cur_depth)
{
    if (node_list.size() <= cur_depth)
    {
        return nullptr;
    }

    size_t      idx, max;
    yyjson_val *key, *val;
    yyjson_val* ret = nullptr;
    yyjson_obj_foreach(obj, idx, max, key, val)
    {
        const char* key_str = yyjson_get_str(key);
        if (key_str == nullptr)
        {
            continue;
        }

        if (node_list[cur_depth] == key_str && (node_list.size() == cur_depth + 1))
        {
            return val;
        }
        else
        {
            switch (yyjson_get_type(val))
            {
                case YYJSON_TYPE_ARR:
                {
                    ret = for_earch_arr(val, node_list, cur_depth);
                    break;
                }
                case YYJSON_TYPE_OBJ:
                {
                    ret = for_earch_obj(val, node_list, cur_depth + 1);
                    break;
                }
                default:
                    break;
            }

            if (ret) return ret;
        }
    }

    return nullptr;
}

/**
 * @brief 获取json节点
 * @param value指定是obj或arr
 * @param node_list指定获取节点，当arr中还有obj时，当前只实现获取第一个obj的节点，但是一般不会这样获取，先不整这个
 具体例子：
     {"scores":{"test":1, "address":{"city":"Wonderland"}}}
     std::vector<std::string> vlist{"scores", "address", "city"};获取到 "Wonderland"

     {"scores":{"test":1, "address":["11", "22"]}}
     std::vector<std::string> vlist{"scores", "address"};获取到 ["11", "22"]
 */
inline yyjson_val* get_node(yyjson_val* value, const std::vector<std::string>& node_list)
{
    if (node_list.empty()) return value;
    switch (yyjson_get_type(value))
    {
        case YYJSON_TYPE_OBJ:
            return for_earch_obj(value, node_list, 0);
        case YYJSON_TYPE_ARR:
            return for_earch_arr(value, node_list, 0);
        default:
            std::cerr << "get_node is not arr or obj" << std::endl;
            break;
    }
    return nullptr;
}
//----------------------------------------------------
inline bool get_val_string(yyjson_val* value_val, uint8_t& value_type, std::string& value)
{
    if (!value_val)
    {
        value_type = 1;
        return false;
    }

    value_type = 0;
    switch (yyjson_get_type(value_val))
    {
        case YYJSON_TYPE_OBJ:
        {
            yyjson_mut_doc* dst_doc = yyjson_mut_doc_new(NULL);
            if (!dst_doc) break;
            do
            {
                yyjson_mut_val* dst_obj = yyjson_mut_obj(dst_doc);
                if (!dst_obj) break;
                yyjson_mut_doc_set_root(dst_doc, dst_obj);
                yyjson::deep_copy_obj(value_val, dst_doc, dst_obj);

                yyjson_write_err err;
                const char*      json = yyjson_mut_write_opts(dst_doc, 0, nullptr, nullptr, &err);
                if (json)
                {
                    value_type = 1;
                    value      = json;
                    free((void*) json);
                }
                else
                {
                    std::cerr << "err: " << err.code << std::endl;
                }
            } while (0);
            yyjson_mut_doc_free(dst_doc);
        }
        break;
        case YYJSON_TYPE_ARR:
        {
            yyjson_mut_doc* dst_doc = yyjson_mut_doc_new(NULL);
            if (!dst_doc) break;
            do
            {
                yyjson_mut_val* dst_arr = yyjson_mut_arr(dst_doc);
                if (!dst_arr) break;
                yyjson_mut_doc_set_root(dst_doc, dst_arr);
                yyjson::deep_copy_arr(value_val, dst_doc, dst_arr);
                yyjson_write_err err;
                const char*      json = yyjson_mut_write_opts(dst_doc, 0, nullptr, nullptr, &err);
                if (json)
                {
                    value_type = 1;
                    value      = json;
                    free((void*) json);
                }
                else
                {
                    std::cerr << "err: " << err.code << std::endl;
                }
            } while (0);
            yyjson_mut_doc_free(dst_doc);
        }
        break;
        case YYJSON_TYPE_STR:
        {
            const char* str = yyjson_get_str(value_val);
            if (str)
            {
                value = str;
            }
        }
        break;
        case YYJSON_TYPE_NUM:
            if (yyjson_is_real(value_val))
            {
                value = std::to_string(yyjson_get_real(value_val));
            }
            else if (yyjson_is_sint(value_val))
            {
                value = std::to_string(yyjson_get_sint(value_val));
            }
            else if (yyjson_is_uint(value_val))
            {
                value = std::to_string(yyjson_get_uint(value_val));
            }
            else if (yyjson_is_int(value_val))
            {
                value = std::to_string(yyjson_get_int(value_val));
            }
            break;
        default:
            break;
    }

    return !value.empty();
}

// json节点转字符串，value_type：1表示json格式数据，其他表示字符串
inline bool get_val_string(yyjson_val* val, const char* key, uint8_t& value_type, std::string& value)
{
    yyjson_val* value_val = yyjson_obj_get(val, key);
    if (!value_val) return false;

    return get_val_string(value_val, value_type, value);
}

/**
 * @brief 创建一个json doc
 * @param out_doc创建的doc文档
 * @param out_root创建的根节点
 * @param obj创建的out_root是obj还是arr
 */
inline bool create(yyjson_mut_doc** out_doc, yyjson_mut_val** out_root, bool is_obj = true)
{
    *out_doc = yyjson_mut_doc_new(NULL);
    if (out_doc == nullptr) return false;
    if (is_obj)
    {
        *out_root = yyjson_mut_obj(*out_doc);
    }
    else
    {
        *out_root = yyjson_mut_arr(*out_doc);
    }
    if (out_root == nullptr)
    {
        yyjson_mut_doc_free(*out_doc);
        *out_doc = nullptr;
        return false;
    }
    yyjson_mut_doc_set_root(*out_doc, *out_root);

    return true;
}

/**
 * @brief 将mut doc转为字符串
 * @param doc
 * @param out_json 成功返回json数据，失败返回错误日志
 */
inline bool SerializeJson(yyjson_mut_doc* doc, std::string& out_json)
{
    yyjson_write_err err;
    const char*      json = yyjson_mut_write_opts(doc, 0, nullptr, nullptr, &err);
    if (json)
    {
        out_json.assign(json);
        free((void*) json);
        return true;
    }

    out_json = "序列化JSON失败,错误码: " + std::to_string(err.code) + ", 出错信息: " + (err.msg ? err.msg : "Unknown error");
    return false;
}
}  // namespace yyjson
